﻿#include "intercom.h"
#include <QJsonObject>
#include <QJsonDocument>
#include "logfile.h"
#include <QDir>
#include <QImage>

Intercom::Intercom(int port, QObject *parent) :
    QObject(parent),
    m_cliMap(),
    m_getMacTimerMap()
{
    m_server = new QTcpServer();
    m_listenPort = port;
}

Intercom::~Intercom()
{
    m_server->close();
    m_server->deleteLater();
    m_timerMutex.lock();
    QMap<QTcpSocket *, QTimer*>::iterator it;
    for(it = m_getMacTimerMap.begin(); it != m_getMacTimerMap.end(); ++it)
    {
        it.key()->close();
        it.key()->deleteLater();
        it.value()->stop();
        it.value()->deleteLater();
    }
    m_timerMutex.unlock();
    m_getMacTimerMap.clear();
    m_cliMap.clear();
}

void Intercom::listen()
{
    QString strLog;
    bool blisten  = m_server->listen(QHostAddress::Any, m_listenPort);
    if(false == blisten)
    {
        ERROR_PRINT<<"m_server listen "<<m_listenPort<<"  error!";
        strLog.sprintf("m_server listen:%d error!",m_listenPort);
        logFile::printLog(strLog);
        return;
    }
    DEBUG_PRINT<<"m_server listen "<<m_listenPort<<"success!";
    strLog.clear();
    strLog.sprintf("m_server listen:%d success!",m_listenPort);
    logFile::printLog(strLog);
    connect(m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    connect(m_server, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(onAcceptError(QAbstractSocket::SocketError)));
}

void Intercom::onNewConnection()
{
    QTcpSocket *newSock = m_server->nextPendingConnection();
    QString strLog("recv new connection from intercom.will require mac..");
    logFile::printLog(strLog);
    WARNING_PRINT << "new connection from intercom.............";
    m_cliMap[newSock] = QString("");
    connect(newSock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onClose(QAbstractSocket::SocketError)));
    connect(newSock, SIGNAL(readyRead()), this, SLOT(onRead()));

    QJsonObject jsonObj;
    QJsonDocument jsonDoc;

    jsonObj["id"] = OPEN_ID_REQUIRE_MAC;
    jsonDoc.setObject(jsonObj);
    newSock->write(jsonDoc.toJson(QJsonDocument::Compact));
    QTimer *timer = new QTimer(this);
    m_getMacTimerMap.insert(newSock, timer);
    connect(timer, SIGNAL(timeout()), this,SLOT(onGetMacTimeout()));
    timer->start(15000); //15s
    timer->setSingleShot(true); //只获取一次
}

void Intercom::onAcceptError(QAbstractSocket::SocketError err)
{
    WARNING_PRINT << "Intercom::onAcceptError: "<< err <<"will  relisten!";
    QString strLog;
    strLog.sprintf("Intercom::onAcceptError : %d, will relisten", err);
    logFile::printLog(strLog);
    m_server->close();
    delete m_server;
    m_server = Q_NULLPTR;
    m_server = new QTcpServer();
    this->listen();
}

void Intercom::onClose(QAbstractSocket::SocketError)
{
    QTcpSocket *sock = (QTcpSocket *)this->sender();
    WARNING_PRINT << "Intercom::onClose..... ";
    QString strLog("Intercom::onClose..");
    logFile::printLog(strLog);
    sock->abort();
    m_cliMap.remove(sock);
    QMap<QTcpSocket *, QTimer*>::iterator it;
    m_timerMutex.lock();
    for(it = m_getMacTimerMap.begin(); it != m_getMacTimerMap.end(); ++it)
    {
        if(it.key() == sock)
        {
            it.value()->stop();
            delete it.value();
            m_getMacTimerMap.erase(it);
            break;
        }
    }
    m_timerMutex.unlock();
}

void Intercom::onRead()
{
    QString strLog;
    QTcpSocket *sock = (QTcpSocket *)this->sender();
    QByteArray tempData = sock->readAll();
    QString tempStr(tempData);
    QString dstStr = tempStr.simplified();
    QByteArray data = dstStr.toLocal8Bit();
    QJsonParseError jsonErr;
    QJsonObject jsonObj;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonErr);

    if (jsonErr.error != QJsonParseError::NoError && !jsonDoc.isObject())
    {
        WARNING_PRINT << "recv unkown msg" << data << jsonErr.error;
        strLog.clear();
        strLog.sprintf("recv unkown msg Json error: %s, errcode:%d, size = %d",data.toStdString().c_str(), jsonErr.error, data.size());
        logFile::printLog(strLog);
        return ;
    }

    jsonObj = jsonDoc.object();

    emit textRecv(data);
    DEBUG_PRINT << "recv src msg from intercom:" << data;
    strLog.clear();
    strLog.sprintf("recv src msg from intercom: %s",data.toStdString().c_str());
    logFile::printLog(strLog);
    switch (jsonObj["id"].toInt())
    {
        case OPEN_ID_REPLY_OPENED:
        case OPEN_ID_REPLY_CLOSED:
        case OPEN_ID_REPLY_ALARM:
        case OPEN_ID_REPLY_ALARM_OVER:
            break;
        case OPEN_ID_REPLY_MAC:
            {
                m_cliMap[sock] = jsonObj["mac"].toString();
                QMap<QTcpSocket *, QTimer*>::iterator it;
                m_timerMutex.lock();
                for(it = m_getMacTimerMap.begin(); it != m_getMacTimerMap.end(); ++it)
                {
                    if(it.key() == sock)
                    {
                        it.value()->stop();
                        delete it.value();
                        strLog.clear();
                        strLog.sprintf("get OPEN_ID_REPLY_MAC remove socktimer!");
                        logFile::printLog(strLog);
                        m_getMacTimerMap.remove(it.key());
                        break;
                    }
                }
                m_timerMutex.unlock();
            }
            break;
        case HEARTBEAT_ID:
            sock->write(data);
            break;
        default:
            {
                WARNING_PRINT << "recv unknown id" << jsonObj["id"].toInt();
                strLog.clear();
                strLog.sprintf("recv unknown id: %d", jsonObj["id"].toInt());
                logFile::printLog(strLog);
            }
            break;
    }
    if(jsonObj["id"].toInt() == OPEN_ID_REPLY_OPENED && !m_cliMap[sock].isEmpty()) //收到开门信息
    {
        QString userid = QString();
        QString strIPC_IP = QString();
        QString strUserid = jsonObj["userid"].toString();
        int nIndex = strUserid.lastIndexOf('^');
        if(-1 != nIndex)
        {
            userid = strUserid.left(nIndex);
            strIPC_IP = strUserid.right(strUserid.size() - nIndex - 1);
            jsonObj["userid"] = userid;
        }
        DEBUG_PRINT << "receive open door msg:" << "mac" << m_cliMap[sock] <<"IPC_IP" << strIPC_IP <<"userid:" << strUserid<< "RealUserid:" << userid;
        strLog.sprintf("receive open door msg:mac=%s,IPC_IP=%s,userid=%s,RealUserid=%s",m_cliMap[sock].toStdString().c_str(),
                       strIPC_IP.toStdString().c_str(),strUserid.toStdString().c_str(),userid.toStdString().c_str());
        logFile::printLog(strLog);

        QString faceimgpath;
        if(!userid.isEmpty() && m_faceImgMap.contains(userid))
        {
            QByteArray jpgface = m_faceImgMap[userid];
            faceimgpath = CommonFuc::getRecordPath();
            faceimgpath.append(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh_mm_ss_zzz_"));
            faceimgpath.append(QString::number(0));//test
            faceimgpath.append(".jpg");

            QFile file(faceimgpath);
            if (file.open(QIODevice::WriteOnly))
            {
                file.write(jpgface);
                file.flush();
                file.close();
            }
            strLog.clear();
            strLog.sprintf("face img save to: %s", faceimgpath.toStdString().c_str());
            logFile::printLog(strLog);
            m_faceImgMap.remove(userid);
        }
        //直接在原有的基础上添加字段
        jsonObj.insert("areaid",g_ConfigFile.m_cfg.general.proxyId);
        jsonObj.insert("mac",m_cliMap[sock]);
        jsonObj.insert("faceimg",faceimgpath);
        jsonObj.insert("opentime", CommonFuc::getCurTime());
        jsonObj.insert("ipc_ip",strIPC_IP);
        jsonDoc.setObject(jsonObj);
        QByteArray resultData = jsonDoc.toJson(QJsonDocument::Compact);
        DEBUG_PRINT << "dealwith msg from intercom:" << "---------"<<resultData;
        switch (jsonObj["openMode"].toInt())
        {
            case OPEN_MODE_ACCESS_CARD: //刷卡开门
            case OPEN_MODE_PASSWD: //密码开门
            case OPEN_MODE_REMOTE: //访客呼叫&&远程开门
            case OPEN_MODE_MANAGER: //一键呼叫管理处
            case OPEN_MODE_APP: //手机APP
            case OPEN_MODE_FACE: //人脸识别
            case OPEN_MODE_IDCARD: //身份证识别
            case OPEN_MODE_FINGERPRINT: //指纹识别
            case OPEN_MODE_WECHAT: //微信开门
            case OPEN_MODE_BUTTON: //按键开门
            {
                 DEBUG_PRINT << "open door ------: "<<jsonObj["openMode"].toInt()<<resultData;
                 //emit sigOpenDoor(resultData,m_cliMap[sock],strIPC_IP);
                 emit sigOpenDoor(resultData);
            }
        }
    }
}

void Intercom::onFaceOpenDoor(QString mac, QString userid, QByteArray jpg)
{
    emit textRecv(mac);
    QList<QTcpSocket *> keys = m_cliMap.keys(mac);

    QString strRealUserid = QString();
    QString strIPC_IP = QString();
    int nIndex = userid.lastIndexOf('^');
    if(-1 != nIndex)
    {
        strRealUserid = userid.left(nIndex);
        strIPC_IP = userid.right(userid.size() - nIndex - 1);
    }

    DEBUG_PRINT << "receive msg:" << "mac" << mac <<"IPC_IP" << strIPC_IP <<"userid:" << userid<< "RealUserid:" << strRealUserid;
    for (int i = 0; i < keys.size(); i++)
    {
        QJsonObject jsonObj;
        QJsonDocument jsonDoc;
        jsonObj["id"] = OPEN_ID_REQUIRE_OPEN;
        jsonObj["openMode"] = OPEN_MODE_FACE;
        jsonObj["userid"] = userid;
        jsonDoc.setObject(jsonObj);
        m_faceImgMap[strRealUserid] = jpg;
        keys.at(i)->write(jsonDoc.toJson(QJsonDocument::Compact));
        emit textRecv(QString("%1").arg(i));
    }
}

void Intercom::onGetMacTimeout()
{
    QString strLog;
    QTimer *timer = (QTimer*)this->sender();
    QMap<QTcpSocket *, QTimer*>::iterator it;
    QJsonObject jsonObj;
    QJsonDocument jsonDoc;
    jsonObj["id"] = OPEN_ID_REQUIRE_MAC;
    jsonDoc.setObject(jsonObj);
    m_timerMutex.lock();
    for(it = m_getMacTimerMap.begin(); it != m_getMacTimerMap.end(); ++it)
    {
        if(it.value() == timer)
        {
            strLog.sprintf("onGetMacTimeout will resend....");
            logFile::printLog(strLog);
            int ret = it.key()->write(jsonDoc.toJson(QJsonDocument::Compact));
            if(ret <= 0)
            {
                strLog.sprintf("onGetMacTimeout resend error, will close socket ");
                logFile::printLog(strLog);
                it.key()->close();
                m_cliMap.remove(it.key());
                it.value()->stop();
                delete it.value();
                m_getMacTimerMap.remove(it.key());
                break;
            }
        }
    }
    m_timerMutex.unlock();
}

